/*
# File    :   fsm_app.c
# Author  :   SCHIPS
# Mail    :   schips@dingtalk.com
# Git     :   https://gitee.com/schips/
# Date    :   Mon, May 27, 2019  8:43:51 AM
*/

#include <stdio.h>
#include "fsm.h"
#include "fsm_app.h"

#define data_entry(p_sm, type, p_data)  ((type) *)(((p_sm))->(var))

/* 内部接口， 不允许外部调用 */
static inline void set_next_state(void* arg, State st);


static inline void empty_data(void *arg);

/*
 *  说明
 *
 *  关于修改状态机的状态，需要按照 如下的 函数类型声明与实现
 *
 *      其次，在状态函数的最后需要用 return 返回 ns(next state)
 *
 * */
State step_init(void * arg)
{
    SM_ARG *p = (SM_ARG *)arg;

    // 状态处理
    set_next_state(arg, s_count);

    // 数据处理
    empty_data(arg);

    return p->st.ns;
}

State step_count(void * arg)//计数
{
    // 下面的三种注释分别 实现 了3种数据域的访问
    SM_ARG *p = (SM_ARG *)arg;
    //SM_DATA *pd = data_entry(p,SM_DATA,p->var); // 1

    if ( ((SM_DATA*)p->var)->cnt < 3)
    {
        //((SM_DATA*)p->var)->cnt++;              // 2
        (data_entry(p,SM_DATA,p->var))->cnt++;    // 3
        //pd->cnt++;                              // 1
        set_next_state(arg, s_count);
    }
    else
    {
        set_next_state(arg, s_done);
    }

    return p->st.ns;
}

State step_done(void * arg)//计数完成
{
    SM_ARG *p = (SM_ARG *)arg;

    // 驻留
    set_next_state(arg, s_done);
    // 可以根据需要让其跳转到 s_init 
    return p->st.ns;
}

State step_default(void * arg)//错误过程
{
    SM_ARG *p = (SM_ARG *)arg;
    set_next_state(arg, s_done);
    return p->st.ns;
}

static inline void empty_data(void* arg)
{
    SM_ARG *p = (SM_ARG *)arg;
    //((SM_DATA*)p->var)->cnt = 0;
    (data_entry(p,SM_DATA,p->var))->cnt = 0;
    p->st.cs = s_init;
    set_next_state(arg, s_count);
}

static inline void set_next_state(void*arg, State st)
{
    SM_ARG *p = (SM_ARG *)arg;
    p->st.ns = st;
}
